package com.sql.compare.controller;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.HikariDataSourceCreator;
import com.baomidou.dynamic.datasource.ds.ItemDataSource;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.sql.compare.dto.DataSourceDTO;
import com.sql.compare.dto.ResultDTO;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.sql.DataSource;
import java.sql.DriverManager;
import java.util.*;

@RestController
@RequestMapping("/datasource")
@Slf4j
public class DataSourceController {
 
    @Autowired
    private DataSource dataSource;
    @Autowired
    private DefaultDataSourceCreator dataSourceCreator;
    @Autowired
    private DruidDataSourceCreator druidDataSourceCreator;
    @Autowired
    private HikariDataSourceCreator hikariDataSourceCreator;
 
    @GetMapping
    public ResultDTO<List<DataSourceDTO>> now() {
        List<DataSourceDTO> list = new ArrayList<>();
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        ds.getDataSources().forEach((k,v) ->{
            ItemDataSource itemDataSource = (ItemDataSource) v;
            DataSourceDTO dataSourceDTO = new DataSourceDTO();
            if (itemDataSource.getDataSource() instanceof DruidDataSource){
                DruidDataSource druidDataSource = (DruidDataSource) itemDataSource.getDataSource();
                BeanUtils.copyProperties(druidDataSource,dataSourceDTO);
            }
            if (itemDataSource.getDataSource() instanceof HikariDataSource){
                HikariDataSource hikariDataSource = (HikariDataSource) itemDataSource.getDataSource();
                BeanUtils.copyProperties(hikariDataSource,dataSourceDTO);
            }
            dataSourceDTO.setPoolName(k);
            list.add(dataSourceDTO);
        });
        return new ResultDTO<>(0,"请求成功",list);
    }
 
    //通用数据源会根据maven中配置的连接池根据顺序依次选择。
    //默认的顺序为druid>hikaricp>
    @PostMapping("/add")
    public Set<String> add(@RequestBody DataSourceDTO dto) {
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        BeanUtils.copyProperties(dto, dataSourceProperty);
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
        ds.addDataSource(dto.getPoolName(), dataSource);
        return ds.getDataSources().keySet();
    }

    /**
     * 添加druid数据源
     * @author xuepeng
     */
    @PostMapping("/addDruid")
    public ResultDTO<String> addDruid(@Validated @RequestBody DataSourceDTO dto) {
        try {
            Class.forName(dto.getDriverClassName());
            DriverManager.getConnection(dto.getUrl(),dto.getUsername(),dto.getPassword());
        } catch (Exception e) {
            log.error("连接失败！！",e);
            return new ResultDTO<>(-1,"创建失败,失败原因：" + e.getMessage(),null);
        }
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        BeanUtils.copyProperties(dto, dataSourceProperty);
        dataSourceProperty.setLazy(true);
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
        ds.addDataSource(dto.getPoolName(), dataSource);
        return new ResultDTO<>(0,"新增数据源成功",null);
    }
 
    @PostMapping("/addHikari")
    public Set<String> addHikari(@RequestBody DataSourceDTO dto) {
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        BeanUtils.copyProperties(dto, dataSourceProperty);
        dataSourceProperty.setLazy(true);//3.4.0版本以下如果有此属性，需手动设置，不然会空指针。
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
        ds.addDataSource(dto.getPoolName(), dataSource);
        return ds.getDataSources().keySet();
    }

    /**
     * 删除数据源
     * @author xuepeng
     */
    @PostMapping("/remove")
    public ResultDTO<String> remove(@RequestBody List<String> poolNames) {
        try {
            DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
            poolNames.forEach(ds::removeDataSource);
        } catch (Exception e) {
            log.error("删除失败",e);
            return new ResultDTO<>(-1,"删除失败"+e.getMessage(),null);
        }
        return new ResultDTO<>(0,"删除成功",null);
    }


    @GetMapping("/databaseByPoolName")
    public ResultDTO<String> databaseByPoolName(String poolName) {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        ItemDataSource itemDataSource = (ItemDataSource) ds.getDataSource(poolName);
        String url = null;
        if (itemDataSource.getDataSource() instanceof DruidDataSource){
            DruidDataSource druidDataSource = (DruidDataSource) itemDataSource.getDataSource();
            url = druidDataSource.getUrl();
        }
        if (itemDataSource.getDataSource() instanceof HikariDataSource){
            HikariDataSource hikariDataSource = (HikariDataSource) itemDataSource.getDataSource();
            url = hikariDataSource.getJdbcUrl();
        }
        if (ObjectUtil.isNotEmpty(url)){
            url = url.substring(url.lastIndexOf("/") + 1, url.contains("?") ? url.indexOf("?") : url.length());
        }
        return new ResultDTO<>(0,"请求成功",url);
    }
}